import pako from "pako";
import { showloading, hideloading } from "../global/loading";
import { luckysheetrefreshgrid, jfrefreshgrid_rhcw } from "../global/refresh";
import editor from "../global/editor";
import { sheetHTML, luckyColor } from "./constant";
import sheetmanage from "./sheetmanage";
import menuButton from "./menuButton";
import { createFilterOptions } from "./filter";
import luckysheetFreezen from "./freezen";
import luckysheetPostil from "./postil";
import imageCtrl from "./imageCtrl";
import dataVerificationCtrl from "./dataVerificationCtrl";
import hyperlinkCtrl from "./hyperlinkCtrl";
import { getObjType, replaceHtml, getByteLen } from "../utils/util";
import { getSheetIndex } from "../methods/get";
import Store from "../store";
import { collaborativeEditBox } from "./select";
import locale from "../locale/locale";
import dayjs from "dayjs";
import json from "../global/json";
import luckysheetConfigsetting from "./luckysheetConfigsetting";
import { customImageUpdate } from "./imageUpdateCtrl";
import method from "../global/method";

const server = {
  gridKey: null,
  loadUrl: null,
  updateUrl: null,
  updateImageUrl: null,
  title: null,
  loadSheetUrl: null,
  retryTimer: null,
  allowUpdate: false, //共享编辑模式
  historyParam: function (data, sheetIndex, range) {
    let _this = this;

    let r1 = range.row[0],
      r2 = range.row[1];
    let c1 = range.column[0],
      c2 = range.column[1];

    if (r1 == r2 && c1 == c2) {
      //单个单元格更新
      let v = data[r1][c1];
      _this.saveParam("v", sheetIndex, v, { r: r1, c: c1 });
    } else {
      //范围单元格更新
      let rowlen = r2 - r1 + 1;
      let collen = c2 - c1 + 1;

      let timeR = Math.floor(1000 / collen);
      let n = Math.ceil(rowlen / timeR); //分批次更新，一次最多1000个单元格

      for (let i = 0; i < n; i++) {
        let str = r1 + timeR * i;

        let edr;
        if (i == n - 1) {
          edr = r2;
        } else {
          edr = r1 + timeR * (i + 1) - 1;
        }

        let v = [];

        for (let r = str; r <= edr; r++) {
          let v_row = [];

          for (let c = c1; c <= c2; c++) {
            if (data[r] == null) {
              v_row.push(null);
            } else {
              v_row.push(data[r][c]);
            }
          }

          v.push(v_row);
        }

        _this.saveParam("rv", sheetIndex, v, {
          range: { row: [str, edr], column: [c1, c2] },
        });

        if (i == n - 1) {
          _this.saveParam("rv_end", sheetIndex, null);
        }
      }
    }
  },
  saveParam: function (type, index, value, params) {
    let _this = this;

    if (!_this.allowUpdate) {
      return;
    }

    if (value == undefined) {
      value = null;
    }

    let d = {};
    d.t = type;
    d.i = index;
    d.v = value;

    //切换sheet页不发后台，TODO：改为发后台+后台不广播
    if (type === "shs") {
      return;
    }

    if (type == "rv") {
      //单元格批量更新
      d.range = params.range;
    } else if (type == "v" || type == "fu" || type == "fm") {
      d.r = params.r;
      d.c = params.c;
    } else if (type == "fc") {
      d.op = params.op;
      d.pos = params.pos;
    } else if (type == "drc" || type == "arc" || type == "h" || type == "wh") {
      d.rc = params.rc;
    } else if (type == "c") {
      d.cid = params.cid;
      d.op = params.op;
    } else if (type == "f") {
      d.op = params.op;
      d.pos = params.pos;
    } else if (type == "s") {
    } else if (type == "sh") {
      d.op = params.op;
      if (params.cur != null) {
        d.cur = params.cur;
      }
    } else if (type == "cg") {
      d.k = params.k;
    } else if (type == "all") {
      d.k = params.k;
      // d.s = params.s;
    }

    // TODO 配置自定义方式同步图片
    const customImageUpdateMethodConfig =
      luckysheetConfigsetting.imageUpdateMethodConfig;
    if (JSON.stringify(customImageUpdateMethodConfig) !== "{}") {
      if ("images" != d.k) {
        let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {
          to: "string",
        });

        if (_this.websocket != null) {
          _this.websocket.send(msg);
        }
      } else {
        customImageUpdate(
          customImageUpdateMethodConfig.method,
          customImageUpdateMethodConfig.url,
          d
        )
          .then((data) => {
            console.log(data);
          })
          .catch((err) => {
            console.log(err);
          });
      }
    } else {
      let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {
        to: "string",
      });
      if (_this.websocket != null) {
        _this.websocket.send(msg);
      }
    }
  },
  websocket: null,
  wxErrorCount: 0,
  openWebSocket: function () {
    let _this = this;

    if ("WebSocket" in window) {
      let wxUrl =
        _this.updateUrl + "?t=111&g=" + encodeURIComponent(_this.gridKey);
      if (_this.updateUrl.indexOf("?") > -1) {
        wxUrl =
          _this.updateUrl + "&t=111&g=" + encodeURIComponent(_this.gridKey);
      }

      _this.websocket = new WebSocket(wxUrl);

      //连接建立时触发
      _this.websocket.onopen = function () {
        console.info(locale().websocket.success);
        hideloading();
        _this.wxErrorCount = 0;

        //防止websocket长时间不发送消息导致断连
        _this.retryTimer = setInterval(function () {
          _this.websocket.send("rub");
        }, 60000);
      };

      //客户端接收服务端数据时触发
      _this.websocket.onmessage = function (result) {
        Store.result = result;
        let data = new Function("return " + result.data)();
        method.createHookFunction("cooperativeMessage", data);
        console.info(data);
        let type = data.type;
        let { message, id } = data;
        // 用户退出时，关闭协同编辑时其提示框
        if (message === "用户退出") {
          $("#luckysheet-multipleRange-show-" + id).hide();
          Store.cooperativeEdit.changeCollaborationSize =
            Store.cooperativeEdit.changeCollaborationSize.filter((value) => {
              return value.id != id;
            });
          Store.cooperativeEdit.checkoutData =
            Store.cooperativeEdit.checkoutData.filter((value) => {
              return value.id != id;
            });
        }
        if (type == 1) {
          //send 成功或失败
          const oldIndex = data.data.v.index;
          const sheetToUpdate = Store.luckysheetfile.filter(
            (sheet) => sheet.index === oldIndex
          )[0];
          if (sheetToUpdate !== null) {
            setTimeout(() => {
              const index = data.data.i;
              sheetToUpdate.index = index;
              Store.currentSheetIndex = index;

              $(`#luckysheet-sheets-item${oldIndex}`).attr("data-index", index);
              $(`#luckysheet-sheets-item${oldIndex}`).prop(
                "id",
                `luckysheet-sheets-item${index}`
              );
              $(`#luckysheet-datavisual-selection-set-${oldIndex}`).prop(
                "id",
                `luckysheet-datavisual-selection-set-${index}`
              );
            }, 1);
          }
        } else if (type == 2) {
          //更新数据
          let item = JSON.parse(data.data);
          _this.wsUpdateMsg(item);
          let chang_data = JSON.parse(data.data);
          if (chang_data.k == "columnlen") {
            collaborativeEditBox(chang_data.v, null);
          } else if (chang_data.k == "rowlen") {
            collaborativeEditBox(null, chang_data.v);
          }
        } else if (type == 3) {
          //多人操作不同选区("t": "mv")（用不同颜色显示其他人所操作的选区）
          let id = data.id;
          let username = data.username;
          let item = JSON.parse(data.data);
          let type = item.t,
            index = item.i,
            value = item.v;
          if (Store.cooperativeEdit.changeCollaborationSize.length === 0) {
            Store.cooperativeEdit.changeCollaborationSize.push({
              id: id,
              v: item.v[0],
              i: index,
            });
          }
          let flag = Store.cooperativeEdit.changeCollaborationSize.some(
            (value1) => {
              return value1.id == id;
            }
          );
          if (flag) {
            Store.cooperativeEdit.changeCollaborationSize.forEach((val) => {
              if (val.id == id) {
                val.v = item.v[0] || item.range[0];
                val.i = index;
              }
            });
          } else {
            Store.cooperativeEdit.changeCollaborationSize.push({
              id: id,
              v: item.v[0],
              i: index,
            });
          }
          if (getObjType(value) != "array" && getObjType(value) !== "object") {
            value = JSON.parse(value);
          }
          let r = 0;
          let c = 0;
          if (index == Store.currentSheetIndex) {
            //发送消息者在当前页面

            if (getObjType(value) === "object" && value.op === "enterEdit") {
              r = value.range[value.range.length - 1].row[0];
              c = value.range[value.range.length - 1].column[0];
              _this.multipleRangeShow(id, username, r, c, value.op);
            } else {
              r = value[value.length - 1].row[0];
              c = value[value.length - 1].column[0];

              _this.multipleRangeShow(id, username, r, c);
            }
          } else {
            if (getObjType(value) === "object" && value.op === "enterEdit") {
              r = value.range[value.range.length - 1].row[0];
              c = value.range[value.range.length - 1].column[0];
            } else {
              r = value[value.length - 1].row[0];
              c = value[value.length - 1].column[0];
            }
          }

          if (Store.cooperativeEdit.checkoutData.length === 0) {
            if (value.op) {
              Store.cooperativeEdit.checkoutData.push({
                id,
                username,
                r,
                c,
                op: value.op,
                index,
              });
            } else {
              Store.cooperativeEdit.checkoutData.push({
                id,
                username,
                r,
                c,
                index,
              });
            }
          }
          let checkoutFlag = Store.cooperativeEdit.checkoutData.some((item) => {
            return item.id == id;
          });
          if (checkoutFlag) {
            Store.cooperativeEdit.checkoutData.forEach((item) => {
              if (item.id == id) {
                item.username = username;
                item.r = r;
                item.c = c;
                item.index = index;
                if (value.op === "enterEdit") {
                  item.op = value.op;
                }
              }
            });
          } else {
            if (value.op === "enterEdit") {
              Store.cooperativeEdit.checkoutData.push({
                id,
                username,
                r,
                c,
                op: value.op,
                index,
              });
            } else {
              Store.cooperativeEdit.checkoutData.push({
                id,
                username,
                r,
                c,
                index,
              });
            }
          }

          //其他客户端切换页面时
          Store.cooperativeEdit.checkoutData.forEach((item) => {
            if (item.index != Store.currentSheetIndex) {
              $("#luckysheet-multipleRange-show-" + item.id).hide();
              item.op == "";
            }
          });

          if ($("#luckysheet-multipleRange-show-" + id)[0]) {
            let change_bottom =
              $("#luckysheet-multipleRange-show-" + id)[0].offsetHeight - 1;
            $("#luckysheet-multipleRange-show-" + id + ">.username").css({
              bottom: change_bottom + "px",
            });
          }
        } else if (type == 4) {
          //批量指令更新
          // let items = JSON.parse(data.data);

          // After editing by multiple people, data.data may appear as an empty string
          let items = data.data === "" ? data.data : JSON.parse(data.data);

          for (let i = 0; i < items.length; i++) {
            _this.wsUpdateMsg(item[i]);
          }
        } else if (type == 5) {
          showloading(data.data);
        } else if (type == 6) {
          hideloading();
        }
      };

      //通信发生错误时触发
      _this.websocket.onerror = function () {
        _this.wxErrorCount++;

        if (_this.wxErrorCount > 3) {
          showloading(locale().websocket.refresh);
        } else {
          showloading(locale().websocket.wait);
          _this.openWebSocket();
        }
      };

      //连接关闭时触发
      _this.websocket.onclose = function (e) {
        console.info(locale().websocket.close);
        if (e.code === 1000) {
          clearInterval(_this.retryTimer);
          _this.retryTimer = null;
        } else {
          alert(locale().websocket.contact);
        }
      };
    } else {
      alert(locale().websocket.support);
    }
  },
  wsUpdateMsg: function (item) {
    let type = item.t,
      index = item.i,
      value = item.v;

    let file = Store.luckysheetfile[getSheetIndex(index)];

    if (
      [
        "v",
        "rv",
        "cg",
        "all",
        "fc",
        "drc",
        "arc",
        "f",
        "fsc",
        "fsr",
        "sh",
        "c",
      ].includes(type) &&
      file == null
    ) {
      return;
    }

    if (type == "v") {
      //单个单元格数据更新
      if (file.data == null || file.data.length == 0) {
        return;
      }

      let r = item.r,
        c = item.c;
      file.data[r][c] = value;

      if (index == Store.currentSheetIndex) {
        //更新数据为当前表格数据
        Store.flowdata = file.data;
        editor.webWorkerFlowDataCache(Store.flowdata); //worker存数据

        //如果更新的单元格有批注
        if (value != null && value.ps != null) {
          luckysheetPostil.buildPs(r, c, value.ps);
        } else {
          luckysheetPostil.buildPs(r, c, null);
        }

        setTimeout(function () {
          luckysheetrefreshgrid();
        }, 1);
      }
    } else if (type == "rv") {
      //范围单元格数据更新
      if (Object.keys(item.range).length > 0) {
        Store.cooperativeEdit.merge_range = item.range;
        Store.cooperativeEdit.merge_range.v = item.v;
        collaborativeEditBox();
      }
      if (file.data == null || file.data.length == 0) {
        return;
      }

      let r1 = item.range.row[0],
        r2 = item.range.row[1];
      let c1 = item.range.column[0],
        c2 = item.range.column[1];

      for (let r = r1; r <= r2; r++) {
        for (let c = c1; c <= c2; c++) {
          file.data[r][c] = value[r - r1][c - c1];
        }
      }

      if (index == Store.currentSheetIndex) {
        //更新数据为当前表格数据
        Store.flowdata = file.data;
        editor.webWorkerFlowDataCache(Store.flowdata); //worker存数据

        //如果更新的单元格有批注
        for (let r = r1; r <= r2; r++) {
          for (let c = c1; c <= c2; c++) {
            if (
              value[r - r1][c - c1] != null &&
              value[r - r1][c - c1].ps != null
            ) {
              luckysheetPostil.buildPs(r, c, value[r - r1][c - c1].ps);
            } else {
              luckysheetPostil.buildPs(r, c, null);
            }
          }
        }

        setTimeout(function () {
          luckysheetrefreshgrid();
        }, 1);
      }
    } else if (type == "cg") {
      //config更新（rowhidden，rowlen，columnlen，merge，borderInfo）
      let k = item.k;

      if (k == "borderInfo") {
        file["config"]["borderInfo"] = value;
      } else {
        if (!(k in file["config"])) {
          file["config"][k] = {};
        }

        // for(let key in value){
        //     file["config"][k][key] = value[key];
        // }

        // ⚠️ 上面的处理方式会导致部分配置项被遗漏，以致协同编辑的时候多视图出现不一致的情况，调整处理的策略为直接替换配置项：
        // 可能的配置项为：
        // columnlen: {0: 65, 1: 186, 2: 52}
        // customHeight: {0: 1, 5: 1, 6: 1}
        // customWidth: {0: 1, 1: 1, 2: 1}
        // merge: {2_1: {…}, 4_2: {…}, 6_2: {…}}
        // rowlen: {0: 19, 5: 93, 6: 117}
        if (value && typeof value == "object") {
          file["config"][k] = value;
        }
      }

      if (index == Store.currentSheetIndex) {
        //更新数据为当前表格数据
        Store.config = file["config"];

        if (k == "rowlen" || k == "columnlen" || k == "rowhidden") {
          jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
        }

        setTimeout(function () {
          luckysheetrefreshgrid();
        }, 1);
      }
    } else if (type == "all") {
      //通用保存更新
      let k = item.k;
      file[k] = value;

      if (k == "name") {
        //工作表名
        $("#luckysheet-sheet-container-c #luckysheet-sheets-item" + index)
          .find("span.luckysheet-sheets-item-name")
          .html(value);
      } else if (k == "color") {
        //工作表颜色
        let currentSheetItem = $(
          "#luckysheet-sheet-container-c #luckysheet-sheets-item" + index
        );
        currentSheetItem.find(".luckysheet-sheets-item-color").remove();

        if (value != null || value != "") {
          currentSheetItem.append(
            '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' +
              value +
              ';"></div>'
          );
        }
      } else if (k == "pivotTable") {
        //PivotTable
        // luckysheet.pivotTable.changePivotTable(index);
      } else if (k == "frozen") {
        //freezen row and column

        // tranform frozen
        luckysheetFreezen.frozenTofreezen();

        if (index == Store.currentSheetIndex) {
          const _locale = locale();
          const locale_freezen = _locale.freezen;
          if (file["freezen"].horizontal == null) {
            $("#luckysheet-freezen-btn-horizontal").html(
              '<i class="fa fa-list-alt"></i> ' + locale_freezen.freezenRow
            );
            luckysheetFreezen.freezenhorizontaldata = null;
            $("#luckysheet-freezebar-horizontal").hide();
          } else {
            luckysheetFreezen.createFreezenHorizontal(
              file["freezen"].horizontal.freezenhorizontaldata,
              file["freezen"].horizontal.top
            );
          }

          if (file["freezen"].vertical == null) {
            $("#luckysheet-freezen-btn-vertical").html(
              '<i class="fa fa-indent"></i> ' + locale_freezen.freezenColumn
            );
            luckysheetFreezen.freezenverticaldata = null;
            $("#luckysheet-freezebar-vertical").hide();
          } else {
            luckysheetFreezen.createFreezenVertical(
              file["freezen"].vertical.freezenverticaldata,
              file["freezen"].vertical.left
            );
          }

          luckysheetFreezen.createAssistCanvas();
        }
      } else if (k == "filter_select") {
        //筛选范围
        if (index == Store.currentSheetIndex) {
          createFilterOptions(value);
        }
      } else if (k == "filter") {
        //筛选保存
        if (index == Store.currentSheetIndex) {
          createFilterOptions(file.filter_select, value);
        }
      } else if (k == "luckysheet_conditionformat_save") {
        //条件格式
        if (index == Store.currentSheetIndex) {
          setTimeout(function () {
            luckysheetrefreshgrid();
          }, 1);
        }
      } else if (k == "luckysheet_alternateformat_save") {
        //交替颜色
        if (index == Store.currentSheetIndex) {
          setTimeout(function () {
            luckysheetrefreshgrid();
          }, 1);
        }
      } else if (k == "config") {
        //config
        if (index == Store.currentSheetIndex) {
          Store.config = value;
          jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length);
        }
      } else if (k == "dynamicArray") {
        //动态数组
        if (index == Store.currentSheetIndex) {
          setTimeout(function () {
            luckysheetrefreshgrid();
          }, 1);
        }
      } else if (k == "images") {
        //图片
        if (index == Store.currentSheetIndex) {
          imageCtrl.images = value;
          imageCtrl.allImagesShow();
          imageCtrl.init();
        }
      } else if (k == "dataVerification") {
        //数据验证
        if (index == Store.currentSheetIndex) {
          dataVerificationCtrl.dataVerification = value;
          dataVerificationCtrl.init();
        }
      } else if (k == "hyperlink") {
        //链接
        if (index == Store.currentSheetIndex) {
          hyperlinkCtrl.hyperlink = value;
          hyperlinkCtrl.init();
        }
      }
    } else if (type == "fc") {
      //函数链calc
      let op = item.op,
        pos = item.pos;

      if (getObjType(value) != "object") {
        value = new Function("return " + value)();
      }

      let r = value.r,
        c = value.c;

      let calcChain = file["calcChain"] == null ? [] : file["calcChain"];

      if (op == "add") {
        calcChain.push(value);
      } else if (op == "del") {
        for (let a = 0; a < calcChain.length; a++) {
          if (
            r == calcChain[a].r &&
            c == calcChain[a].c &&
            index == calcChain[a].index
          ) {
            calcChain.splice(a, 1);
          }
        }
      }
      // else if(op == "update"){
      //     for(let a = 0; a < calcChain.length; a++){
      //         if(r == calcChain[a].r && c == calcChain[a].c && index == calcChain[a].index){
      //             calcChain[a].func = func;
      //         }
      //     }
      // }

      setTimeout(function () {
        luckysheetrefreshgrid();
      }, 1);
    } else if (type == "drc") {
      //删除行列
      if (file.data == null || file.data.length == 0) {
        return;
      }

      let rc = item.rc,
        st_i = value.index,
        len = value.len,
        mc = value.mc,
        borderInfo = value.borderInfo;
      let data = file.data;

      if (rc == "r") {
        file["row"] -= len;

        data.splice(st_i, len);

        //空白行模板
        let row = [];
        for (let c = 0; c < data[0].length; c++) {
          row.push(null);
        }

        //删除多少行，增加多少行空白行
        for (let r = 0; r < len; r++) {
          data.push(row);
        }
      } else {
        file["column"] -= len;

        //空白列模板
        let addcol = [];
        for (let r = 0; r < len; r++) {
          addcol.push(null);
        }

        for (let i = 0; i < data.length; i++) {
          data[i].splice(st_i, len);

          data[i] = data[i].concat(addcol);
        }
      }

      for (let x in mc) {
        let r = mc[x].r,
          c = mc[x].c;
        data[r][c].mc = mc[x];
      }

      file["config"].merge = mc;
      file["config"].borderInfo = borderInfo;

      if (index == Store.currentSheetIndex) {
        Store.flowdata = data;
        editor.webWorkerFlowDataCache(Store.flowdata); //worker存数据

        Store.config["merge"] = mc;
        Store.config["borderInfo"] = borderInfo;

        setTimeout(function () {
          luckysheetrefreshgrid();
        }, 1);
      }
    } else if (type == "arc") {
      //增加行列
      if (file.data == null || file.data.length == 0) {
        return;
      }

      let rc = item.rc,
        st_i = value.index,
        len = value.len,
        addData = value.data,
        direction = value.direction,
        mc = value.mc,
        borderInfo = value.borderInfo;
      let data = $.extend(true, [], file.data);

      if (rc == "r") {
        file["row"] += len;

        //空行模板
        let row = [];
        for (let c = 0; c < data[0].length; c++) {
          row.push(null);
        }

        let arr = [];
        for (let i = 0; i < len; i++) {
          if (addData[i] == null) {
            arr.push(JSON.stringify(row));
          } else {
            arr.push(JSON.stringify(addData[i]));
          }
        }

        if (direction == "lefttop") {
          if (st_i == 0) {
            new Function(
              "data",
              "return " + "data.unshift(" + arr.join(",") + ")"
            )(data);
          } else {
            new Function(
              "data",
              "return " + "data.splice(" + st_i + ", 0, " + arr.join(",") + ")"
            )(data);
          }
        } else {
          new Function(
            "data",
            "return " +
              "data.splice(" +
              (st_i + 1) +
              ", 0, " +
              arr.join(",") +
              ")"
          )(data);
        }
      } else {
        file["column"] += len;

        for (let i = 0; i < data.length; i++) {
          /* 在每一行的指定位置都插入一列 */
          for (let j = 0; j < len; j++) {
            if (direction == "lefttop") {
              data[i].splice(st_i, 0, addData[j]);
            } else {
              data[i].splice(st_i + 1, 0, addData[j]);
            }
          }
        }
      }

      for (let x in mc) {
        let r = mc[x].r,
          c = mc[x].c;
        data[r][c].mc = mc[x];
      }

      file.data = data;
      file["config"].merge = mc;
      file["config"].borderInfo = borderInfo;

      if (index == Store.currentSheetIndex) {
        Store.flowdata = data;
        editor.webWorkerFlowDataCache(Store.flowdata); //worker存数据

        Store.config["merge"] = mc;
        Store.config["borderInfo"] = borderInfo;

        setTimeout(function () {
          luckysheetrefreshgrid();
        }, 1);
      }
    } else if (type == "f") {
      //筛选
      let op = item.op,
        pos = item.pos;

      let filter = file.filter;

      if (filter == null) {
        filter = {};
      }

      if (op == "upOrAdd") {
        filter[pos] = value;
      } else if (op == "del") {
        delete filter[pos];
      }

      if (index == Store.currentSheetIndex) {
        createFilterOptions(file.filter_select, filter);
      }
    } else if (type == "fsc") {
      //清除筛选
      file.filter = null;
      file.filter_select = null;

      if (index == Store.currentSheetIndex) {
        $(
          "#luckysheet-filter-selected-sheet" +
            Store.currentSheetIndex +
            ", #luckysheet-filter-options-sheet" +
            Store.currentSheetIndex
        ).remove();
        $("#luckysheet-filter-menu, #luckysheet-filter-submenu").hide();
      }
    } else if (type == "fsr") {
      //恢复筛选
      file.filter = value.filter;
      file.filter_select = value.filter_select;

      if (index == Store.currentSheetIndex) {
        createFilterOptions(file.filter_select, file.filter);
      }
    } else if (type == "sha") {
      //新建sheet
      Store.luckysheetfile.push(value);

      let colorset = "";
      if (value.color != null) {
        colorset =
          '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' +
          value.color +
          ';"></div>';
      }

      $("#luckysheet-sheet-container-c").append(
        replaceHtml(sheetHTML, {
          index: value.index,
          active: "",
          name: value.name,
          style: "",
          colorset: colorset,
        })
      );
      $("#luckysheet-cell-main").append(
        '<div id="luckysheet-datavisual-selection-set-' +
          value.index +
          '" class="luckysheet-datavisual-selection-set"></div>'
      );

      // *添加sheet之后,要判断是否需要显示sheet滚动按钮
      sheetmanage.locationSheet();
    } else if (type == "shc") {
      //复制sheet
      let copyindex = value.copyindex,
        name = value.name;

      let copyarrindex = getSheetIndex(copyindex);
      let copyjson = $.extend(true, {}, Store.luckysheetfile[copyarrindex]);

      copyjson.index = index;
      copyjson.name = name;

      Store.luckysheetfile.splice(copyarrindex + 1, 0, copyjson);

      let copyobject = $("#luckysheet-sheets-item" + copyindex);
      $("#luckysheet-sheet-container-c").append(
        replaceHtml(sheetHTML, {
          index: copyjson.index,
          active: "",
          name: copyjson.name,
          style: "",
          colorset: "",
        })
      );
      $("#luckysheet-sheets-item" + copyjson.index).insertAfter(copyobject);
      $("#luckysheet-cell-main").append(
        '<div id="luckysheet-datavisual-selection-set-' +
          copyjson.index +
          '" class="luckysheet-datavisual-selection-set"></div>'
      );
    } else if (type == "shd") {
      //删除sheet
      for (let i = 0; i < Store.luckysheetfile.length; i++) {
        if (Store.luckysheetfile[i].index == value.deleIndex) {
          // 如果删除的是当前sheet，则切换到前一个sheet页
          if (Store.currentSheetIndex === value.deleIndex) {
            const index = value.deleIndex;

            Store.luckysheetfile[sheetmanage.getSheetIndex(index)].hide = 1;

            let luckysheetcurrentSheetitem = $(
              "#luckysheet-sheets-item" + index
            );
            luckysheetcurrentSheetitem.hide();

            $("#luckysheet-sheet-area div.luckysheet-sheets-item").removeClass(
              "luckysheet-sheets-item-active"
            );

            let indicator = luckysheetcurrentSheetitem.nextAll(":visible");
            if (luckysheetcurrentSheetitem.nextAll(":visible").length > 0) {
              indicator = indicator.eq(0).data("index");
            } else {
              indicator = luckysheetcurrentSheetitem
                .prevAll(":visible")
                .eq(0)
                .data("index");
            }
            $("#luckysheet-sheets-item" + indicator).addClass(
              "luckysheet-sheets-item-active"
            );

            sheetmanage.changeSheetExec(indicator);
          }

          server.sheetDeleSave.push(Store.luckysheetfile[i]);

          Store.luckysheetfile.splice(i, 1);

          break;
        }
      }

      $("#luckysheet-sheets-item" + value.deleIndex).remove();
      $("#luckysheet-datavisual-selection-set-" + value.deleIndex).remove();
      sheetmanage.locationSheet();
    } else if (type == "shr") {
      //sheet位置
      for (let x in value) {
        Store.luckysheetfile[getSheetIndex(x)].order = value[x];
      }
    } else if (type == "shre") {
      //删除sheet恢复操作
      for (let i = 0; i < server.sheetDeleSave.length; i++) {
        if (server.sheetDeleSave[i].index == value.reIndex) {
          let datav = server.sheetDeleSave[i];

          Store.luckysheetfile.push(datav);

          let colorset = "";
          if (value.color != null) {
            colorset =
              '<div class="luckysheet-sheets-item-color" style=" position: absolute; width: 100%; height: 3px; bottom: 0px; left: 0px; background-color: ' +
              datav.color +
              ';"></div>';
          }

          $("#luckysheet-sheet-container-c").append(
            replaceHtml(sheetHTML, {
              index: datav.index,
              active: "",
              name: datav.name,
              style: "",
              colorset: colorset,
            })
          );
          $("#luckysheet-cell-main").append(
            '<div id="luckysheet-datavisual-selection-set-' +
              datav.index +
              '" class="luckysheet-datavisual-selection-set"></div>'
          );
          break;
        }
      }
    } else if (type == "sh") {
      //隐藏sheet
      let op = item.op,
        cur = item.cur;

      if (op == "hide") {
        file.hide = 1;
        $("#luckysheet-sheets-item" + index).hide();

        if (index == Store.currentSheetIndex) {
          $("#luckysheet-sheets-item" + cur).addClass(
            "luckysheet-sheets-item-active"
          );
          sheetmanage.changeSheetExec(cur);
        }
      } else if (op == "show") {
        file.hide = 0;
        $("#luckysheet-sheets-item" + index).show();
      }
      sheetmanage.locationSheet();
    } else if (type == "c") {
      //图表操作 TODO
      let op = item.op,
        cid = item.cid;

      if (op == "add") {
        //插入
        file.chart.push(value);

        luckysheet.insertChartTosheet(
          value.sheetIndex,
          value.dataSheetIndex,
          value.option,
          value.chartType,
          value.selfOption,
          value.defaultOption,
          value.row,
          value.column,
          value.chart_selection_color,
          value.chart_id,
          value.chart_selection_id,
          value.chartStyle,
          value.rangeConfigCheck,
          value.rangeRowCheck,
          value.rangeColCheck,
          value.chartMarkConfig,
          value.chartTitleConfig,
          value.winWidth,
          value.winHeight,
          value.scrollLeft1,
          value.scrollTop1,
          value.chartTheme,
          value.myWidth,
          value.myHeight,
          value.myLeft,
          value.myTop,
          value.myindexrank1,
          true
        );
      } else if (op == "xy" || op == "wh" || op == "update") {
        //移动 缩放 更新
        for (let i = 0; i < file.chart.length; i++) {
          let chartjson = file.chart[i];

          if (chartjson.chart_id == cid) {
            for (let item in chartjson) {
              for (let vitem in value) {
                if (item == vitem) {
                  chartjson[item] = value[vitem];
                }
              }
            }

            sheetmanage.saveChart(chartjson);

            return;
          }
        }
      } else if (op == "del") {
        //删除
        for (let i = 0; i < file.chart.length; i++) {
          let chartjson = file.chart[i];

          if (chartjson.chart_id == cid) {
            file.chart.splice(i, 1);

            $("#" + cid).remove();
            sheetmanage.delChart(
              $("#" + cid).attr("chart_id"),
              $("#" + cid).attr("sheetIndex")
            );

            return;
          }
        }
      }
    } else if (type == "na") {
      //表格名称
      $("#luckysheet_info_detail_input")
        .val(value)
        .css("width", getByteLen(value) * 10);
    }
  },
  multipleIndex: 0,
  multipleRangeShow: function (id, name, r, c, value) {
    let _this = this;
    const fullName = name;

    let row = Store.visibledatarow[r],
      row_pre = r - 1 == -1 ? 0 : Store.visibledatarow[r - 1],
      col = Store.visibledatacolumn[c],
      col_pre = c - 1 == -1 ? 0 : Store.visibledatacolumn[c - 1];

    let margeset = menuButton.mergeborer(Store.flowdata, r, c);
    if (!!margeset) {
      row = margeset.row[1];
      row_pre = margeset.row[0];

      col = margeset.column[1];
      col_pre = margeset.column[0];
    }

    // *处理光标在靠左或者靠上顶着的时候，光标显示不全的问题
    if (col_pre <= 0) {
      col_pre += 1;
    }

    if (row_pre <= 0) {
      row_pre += 1;
    }

    // 超出16个字符就显示...
    if (getByteLen(name) > 16) {
      name = getByteLen(name, 16) + "...";
    }

    // 如果正在编辑，就显示“正在输入”
    if (value === "enterEdit") {
      name += " " + locale().edit.typing;
    }

    if ($("#luckysheet-multipleRange-show-" + id).length > 0) {
      $("#luckysheet-multipleRange-show-" + id).css({
        position: "absolute",
        left: col_pre - 1,
        width: col - col_pre - 1,
        top: row_pre - 1,
        height: row - row_pre - 1,
      });

      $("#luckysheet-multipleRange-show-" + id + " .username").text(name);
      $("#luckysheet-multipleRange-show-" + id + " .username").show();

      if (Store.cooperativeEdit.usernameTimeout["user" + id] != null) {
        clearTimeout(Store.cooperativeEdit.usernameTimeout["user" + id]);
      }
      Store.cooperativeEdit.usernameTimeout["user" + id] = setTimeout(() => {
        clearTimeout(Store.cooperativeEdit.usernameTimeout["user" + id]);
        Store.cooperativeEdit.usernameTimeout["user" + id] = null;
      }, 10 * 1000);
    } else {
      // let itemHtml = '<div id="luckysheet-multipleRange-show-'+ id +'" data-color="'+ luckyColor[_this.multipleIndex] +'" title="'+ name +'" style="position: absolute;left: '+ (col_pre - 1) +'px;width: '+ (col - col_pre - 1) +'px;top: '+ (row_pre - 1) +'px;height: '+ (row - row_pre - 1) +'px;border: 1px solid '+ luckyColor[_this.multipleIndex] +';z-index: 15;">'+
      //                 '<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: '+ luckyColor[_this.multipleIndex] +'"></div>'+
      //                '</div>';

      let itemHtml = `<div
								id="luckysheet-multipleRange-show-${id}"
								class="luckysheet-multipleRange-show"
								data-color="${luckyColor[_this.multipleIndex]}"
								title="${fullName}"
								style="position: absolute;left: ${col_pre - 1}px;width: ${
        col - col_pre - 1
      }px;top: ${row_pre - 1}px;height: ${
        row - row_pre - 1
      }px;border: 1px solid ${luckyColor[_this.multipleIndex]};z-index: 15;">

								<div class="username" style="height: 19px;line-height:19px;width: max-content;position: absolute;bottom: ${
                  row - row_pre - 1
                }px;right: 0;background-color: ${
        luckyColor[_this.multipleIndex]
      };color:#ffffff;padding:0 10px;">
								${name}
								</div>

								<div style="width: 100%;height: 100%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;opacity: 0.03;background-color: ${
                  luckyColor[_this.multipleIndex]
                }">
								</div>

							</div>`;
      // 正在输入

      $(itemHtml).appendTo(
        $("#luckysheet-cell-main #luckysheet-multipleRange-show")
      );

      _this.multipleIndex++;

      // 设定允许用户名消失的定时器，10秒后用户名可隐藏
      // 10秒之类，用户操作界面不会隐藏用户名；10秒之后如果用户操作了界面，则隐藏用户名，没操作就不隐藏
      if (Store.cooperativeEdit.usernameTimeout["user" + id] != null) {
        clearTimeout(Store.cooperativeEdit.usernameTimeout["user" + id]);
      }
      Store.cooperativeEdit.usernameTimeout["user" + id] = setTimeout(() => {
        clearTimeout(Store.cooperativeEdit.usernameTimeout["user" + id]);
        Store.cooperativeEdit.usernameTimeout["user" + id] = null;
      }, 10 * 1000);
    }
  },
  sheetDeleSave: [], //共享编辑模式下 删除的sheet保存下来，方便恢复时取值
  submitInterval: 1000,
  imagesubmitInterval: 5000,
  submitdatalimit: 50,
  submitcompresslimit: 1000,
  checksubmit: function (data) {
    let _this = this;
    //clearTimeout(_this.requestTimeOut);

    _this.submitTimeout();

    clearTimeout(_this.imageRequestTimeout);
    _this.imageRequestTimeout = setTimeout(function () {
      _this.imageRequest();
    }, _this.imagesubmitInterval);
  },
  submitTimeout: function () {
    let _this = this;
    clearTimeout(_this.requestTimeOut);

    //console.log(_this.requestlast, dayjs(), (_this.requestlast!=null && _this.requestlast.add(10, 'seconds').isBefore(dayjs()) ) );
    if (
      !_this.requestLock &&
      _this.requestlast != null &&
      _this.requestlast.clone().add(1, "seconds").isBefore(dayjs())
    ) {
      _this.request();
    }

    // if(!_this.imageRequestLock && (_this.imageRequestLast==null || _this.imageRequestLast.clone().add(30, 'seconds').isBefore(dayjs()) ) ){

    // }

    _this.requestTimeOut = setTimeout(function () {
      _this.submitTimeout();
    }, _this.submitInterval);
  },
  requestLock: false,
  requestlast: null,
  firstchange: true,
  requestTimeOut: null,
  request: function () {
    let _this = this;
    let key = this.gridKey;
    let cahce_key = key + "__qkcache";

    _this.cachelocaldata(function (cahce_key, params) {
      if (params.length == 0) {
        return;
      }

      params = encodeURIComponent(JSON.stringify(params));
      let compressBeginLen = params.length;
      let iscommpress = false;
      // if (compressBeginLen > _this.submitcompresslimit) {
      //     params = pako.gzip(params, { to: "string" });
      //     iscommpress = true;
      // }
      _this.requestLock = true;
      //console.log(params);
      // console.log("request");
      if (_this.updateUrl != "") {
        $.post(
          _this.updateUrl,
          { compress: iscommpress, gridKey: _this.gridKey, data: params },
          function (data) {
            let re = new Function("return " + data)();
            if (re.status) {
              $("#luckysheet_info_detail_update").html(
                "最近存档时间:" + dayjs().format("M-D H:m:s")
              );
              $("#luckysheet_info_detail_save").html("同步成功");
              _this.clearcachelocaldata();
            } else {
              $("#luckysheet_info_detail_save").html(
                "<span style='color:#ff2121'>同步失败</span>"
              );
              _this.restorecachelocaldata();
            }
            _this.requestlast = dayjs();
            _this.requestLock = false;
          }
        );
      }
    });
  },
  imageRequestLast: null,
  imageRequestLock: false,
  imageRequestTimeout: null,
  imageRequest: function () {
    let _this = this;

    html2canvas(
      $("#" + container)
        .find(".luckysheet-grid-window")
        .get(0),
      {
        onrendered: function (canvas) {
          //let imgcut = $("#luckysheet-cell-main").find(".luckysheet-grid-window");
          //document.body.appendChild(canvas);
          let old = $(canvas).appendTo("body");
          old.hide();
          let newwidth = old.width();
          let newheight = old.height();
          let imageData = old
            .get(0)
            .getContext("2d")
            .getImageData(0, 0, newwidth, newheight);

          let cutW = newwidth,
            cutH = newheight;
          if (cutW * 0.54 > cutH) {
            cutW = cutH / 0.54;
          } else {
            cutH = cutW * 0.54;
          }
          let newCanvas = $("<canvas>")
            .attr("width", cutW)
            .attr("height", cutH)[0];

          newCanvas.getContext("2d").putImageData(imageData, 0, 0);

          old.attr("width", 350);
          old.attr("height", 189);
          old.get(0).getContext("2d").drawImage(newCanvas, 0, 0, 350, 189);
          let base64 = old.get(0).toDataURL("image/jpeg", 0.9);

          //console.log(base64);
          //console.log("压缩：", pako.gzip(base64, { to: "string" }));
          //console.log("imageRequest");
          let curindex = luckysheet.sheetmanage.getCurSheetnoset();
          _this.imageRequestLock = true;
          // let data1 = pako.gzip(encodeURIComponent(JSON.stringify({"t":"thumb", "img": base64, "curindex":curindex })), { to: "string" });
          let data1 = encodeURIComponent(
            JSON.stringify({ t: "thumb", img: base64, curindex: curindex })
          );
          old.remove();
          //console.log("缩略图", _this.imageRequestLast,base64);
          if (_this.updateImageUrl != "") {
            // $.post(_this.updateImageUrl, { compress: true, gridKey: _this.gridKey, data:data1  }, function (data) {
            $.post(
              _this.updateImageUrl,
              { compress: false, gridKey: _this.gridKey, data: data1 },
              function (data) {
                let re = new Function("return " + data)();
                if (re.status) {
                  imageRequestLast = dayjs();
                } else {
                  $("#luckysheet_info_detail_save").html(
                    "<span style='color:#ff2121'>网络不稳定</span>"
                  );
                }
                _this.imageRequestLock = true;
              }
            );
          }
        },
      }
    );
  },
  localdata: [],
  matchOpt: function (v, d) {
    for (let vitem in v) {
      if (
        vitem == "t" &&
        v["t"] in { drc: 1, arc: 1, sha: 1, shc: 1, shd: 1 }
      ) {
        return false;
      }

      if (vitem == "v") {
        continue;
      }

      if (!(vitem in d)) {
        return false;
      }

      if (d[vitem] != v[vitem]) {
        return false;
      }
    }

    return true;
  },
  deleteRepeatOpt: function (data, value) {
    //let d = $.extend(true, [], data); //原来
    let d = data;
    let _this = this;

    if (value instanceof Array) {
      for (let i = 0; i < value.length; i++) {
        let vitem = value[i];

        for (let a = 0; a < d.length; a++) {
          let ditem = data[i]; //let ditem = data[a];?

          if (_this.matchOpt(vitem, ditem)) {
            delete d[a];
          }
        }
      }
    } else {
      for (let a = 0; a < d.length; a++) {
        let ditem = d[a];

        if (_this.matchOpt(value, ditem)) {
          delete d[a];
        }
      }
    }

    let ret = [];
    for (let i = 0; i < d.length; i++) {
      if (d[i] != null) {
        ret.push(d[i]);
      }
    }

    return ret;
  },
  setlocaldata: function (value, func) {
    let key = this.gridKey;
    //store.push(key, data);
    let _this = this;
    _this.getlocaldata(function (data) {
      if (data == null) {
        data = [];
      }

      //此处不去重，在request同步后台时统一循环一次去重
      //let data = _this.deleteRepeatOpt(data, value);

      if (value instanceof Array) {
        data = data.concat(value);
      } else {
        data.push(value);
      }

      _this.localdata = data;
      func(_this.localdata);

      //console.log(value);
      // localforage.setItem(key, data).then(function () {
      //     console.log(data);
      //     func(data);
      // }).catch(function (err) {

      // });
    });
  },
  getlocaldata: function (func) {
    let key = this.gridKey;
    //return store.get(key);
    func(this.localdata);
    // localforage.getItem(key).then(function(readValue) {
    //     func(readValue);
    // });
  },
  clearlocaldata: function (func) {
    let key = this.gridKey;
    //store.remove(key);
    this.localdata = [];
    func();
    // localforage.removeItem(key, function(err,value) {
    //     func();
    // });
  },
  cachelocaldata: function (func) {
    let key = this.gridKey;
    let _this = this;
    let cahce_key = key + "__qkcache";
    //store.remove(key);
    //console.log(key, cahce_key);

    //处理localdata去重
    let updatedata = _this.localdata;
    let uLen = updatedata.length;
    if (uLen > 1) {
      let prevData = [];
      prevData[0] = updatedata[0];
      for (let i = 1; i < uLen; i++) {
        let value = updatedata[i];
        let flag = true;
        for (let a = 0; a < prevData.length; a++) {
          let ditem = prevData[a];
          if (_this.matchOpt(value, ditem)) {
            prevData.splice(a, 1, value);
            flag = false; //如果已匹配重复，则后续无需再加
            break;
          }
        }
        if (flag) {
          prevData = prevData.concat(value);
        }
      }
      updatedata = prevData;
    }
    if (updatedata == null || updatedata.length == 0) {
      return;
    }
    //console.log(key, cahce_key,updatedata);
    _this.clearlocaldata(function () {
      localforage.setItem(cahce_key, updatedata).then(function () {
        func(cahce_key, updatedata);
      });
    });

    // localforage.getItem(key).then(function(readValue) {
    //     let updatedata = readValue;
    //     if(readValue==null || readValue.length==0){
    //         return;
    //     }
    //     //console.log(key, cahce_key,updatedata);
    //     _this.clearlocaldata(function(){
    //         localforage.setItem(cahce_key, updatedata).then(function () {
    //             func(cahce_key, updatedata);
    //         });
    //     });
    // });
  },
  clearcachelocaldata: function (func) {
    let key = this.gridKey;
    let cahce_key = key + "__qkcache";
    //store.remove(key);
    localforage.removeItem(cahce_key, function (err, value) {
      if (func && typeof func == "function") {
        func();
      }
    });
  },
  restorecachelocaldata: function (func) {
    let key = this.gridKey;
    let cahce_key = key + "__qkcache";
    let _this = this;
    localforage.getItem(cahce_key).then(function (readValue) {
      let updatedata = readValue;
      _this.getlocaldata(function (data) {
        if (data == null) {
          data = [];
        }
        let newdata = updatedata.concat(data);
        //data.unshift(updatedata);

        _this.localdata = newdata;
        if (func instanceof Function) {
          func(_this.localdata);
        }

        // localforage.setItem(key, newdata).then(function () {
        //     func(newdata);
        // }).catch(function (err) {

        // });
      });
    });
  },
  keepHighLightBox: function () {
    Store.cooperativeEdit.checkoutData.forEach((value) => {
      if (value.index == Store.currentSheetIndex) {
        if (value.op === "enterEdit") {
          server.multipleRangeShow(
            value.id,
            value.username,
            value.r,
            value.c,
            value.op
          );
        } else {
          server.multipleRangeShow(value.id, value.username, value.r, value.c);
        }
      }
    });
  },
};

export default server;
